import logging.config
from pathlib import Path
from typing import Union

from PySide6.QtCore import QObject, QStandardPaths

from .singleton import Singleton
from .setting import APP_NAME

logging.config.fileConfig('logger.conf')
logger = logging.getLogger(__name__)


class ConfigValidator:
    """ Config validator """

    def validate(self, value) -> bool:
        """ Verify whether the value is legal """
        return True

    def correct(self, value):
        """ correct illegal value """
        return value


class FolderValidator(ConfigValidator):
    """ Folder validator """

    def validate(self, value: Union[str, Path]) -> bool:
        return Path(value).exists()

    def correct(self, value: Union[str, Path]):
        path = Path(value)
        try:
            path.mkdir(exist_ok=True, parents=True)
        except Exception as e:
            pass
        return str(path.absolute()).replace("\\", "/")


class ConfigSerializer:
    """ Config serializer """

    @staticmethod
    def serialize(value):
        """ serialize config value """
        return value

    @staticmethod
    def deserialize(value):
        """ deserialize config from config file's value """
        return value


class ConfigItem:
    """ Config item """

    def __init__(self, group: str, name: str, default, validator: ConfigValidator = None,
                 serializer: ConfigSerializer = None, restart=False):
        """
        Parameters
        ----------
        group: str
            config group name

        name: str
            config item name, can be empty

        default:
            default value

        options: list
            options value

        serializer: ConfigSerializer
            config serializer

        restart: bool
            whether to restart the application after updating the configuration item
        """
        self.group = group
        self.name = name
        self.validator = validator or ConfigValidator()
        self.serializer = serializer or ConfigSerializer()
        self.__value = default
        self.value = default
        self.restart = restart

    @property
    def value(self):
        """ get the value of config item """
        return self.__value

    @value.setter
    def value(self, v):
        self.__value = self.validator.correct(v)

    @property
    def key(self):
        """ get the config key separated by `.` """
        return self.group + "." + self.name if self.name else self.group

    def serialize(self):
        return self.serializer.serialize(self.value)

    def deserializeFrom(self, value):
        self.value = self.serializer.deserialize(value)


@Singleton
class Config(QObject):
    cacheFolder = ConfigItem(
        "Folders", "CacheFolder",
        Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppLocalDataLocation)) / APP_NAME,
        FolderValidator(), restart=True)

    @staticmethod
    def get(item: ConfigItem):
        return item.value
